<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="root"></div>
  <ul>
    <li><a id="page1">page1</a></li>
    <li><a id="page2">page2</a></li>
  </ul>
  <script>
    const root = document.getElementById('root')
    const globalHistory = window.history

    // 自定义 ( 事件 ) 属性 onpushstate 当调用 history.pushState 时触发
    window.onpushstate = function (event) {
      console.log('onpushstate event', event)
      // 修改 root 元素内容为浏览器地址栏中的 pathname ( 不包含 hash 和查询参数 )
      root.innerHTML = window.location.pathname
    }

    // 会触发 popstate 事件的方法
    //history.back() 后退一个 history
    //history.forward() 前进一个 hisotry
    //history.go() 根据参数来选择前进还是后退
    window.addEventListener('popstate', (event) => {
      // event.state 获取当前 history 的状态对象
      // 也可以通过 history.state 来获取当前 history 的状态对象
      console.log(event.type, event.state, globalHistory.state)
      root.innerHTML = window.location.pathname
    })

      ; (function (globalHistory) {
        let oldPushState = globalHistory.pushState
        // 重写原生的 history.pushState 方法
        globalHistory.pushState = function (state, title, pathname) {
          // 调用原始的 history.pushState 方法时指定 this 为 history 同时传递 arguments 参数
          let result = oldPushState.apply(globalHistory, arguments)
          if (typeof window.onpushstate === 'function') {
            // 传递一个对象来模拟 事件对象
            window.onpushstate({ type: "pushstate", state })
          }
          return result
        }
      })(globalHistory)

    setTimeout(() => {
      // history 的 state 状态对象可以获取 pushState 传递的第一个参数
      // 也可以在 popstate 事件 event.state 中获取 
      // pushState 不会触发原生 popstate 事件
      globalHistory.pushState({ page: 1 }, "", "/page1")
    }, 1000)

    setTimeout(() => {
      globalHistory.pushState({ page: 2 }, "", '/page2')
    }, 1000 * 2)

    setTimeout(() => {
      globalHistory.pushState({ page: 3 }, "", '/page3')
    }, 1000 * 3)

    setTimeout(() => {
      globalHistory.back()
    }, 1000 * 4)

    setTimeout(() => {
      globalHistory.pushState({ page: 4 }, "", '/page4')
    }, 1000 * 5)

    setTimeout(() => {
      globalHistory.go(1)
    }, 1000 * 6)

    // 最终会跳转到 /page4
    // 1. globalHistory.back() 回退 1 个 history 后当前是 /page2
    // 2. 调用 globalHistory.pushState 添加一个 hisotry 会在 /page2 栈的上面添加一个 /page4

    const page1 = document.getElementById('page1')
    page1.addEventListener('click', () => {
      globalHistory.pushState({ page: 1 }, "", '/page1')
    })
    const page2 = document.getElementById('page2')
    page2.addEventListener('click', () => {
      globalHistory.pushState({ page: 2 }, "", '/page2')
    })
  </script>
</body>

</html>
